package com.china.cnlongdb.server.connect.nettymission;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.alibaba.fastjson.JSON;
import com.china.cnlongdb.basic.constant.LongDbConstant;
import com.china.cnlongdb.basic.entity.datasync.CnLongDataSyncRequest;
import com.china.cnlongdb.basic.enums.sysnc.LongdbDataSyncEnms;
import com.china.cnlongdb.server.connect.nettymission.handler.NettyClientHandler;
import com.china.cnlongdb.server.connect.nettymission.operator.SendNettyRequest;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 系统名称：LongdbNettyClient.java
 * 模块名称：
 * 模块描述：netty-网络通信客户端
 * 功能列表：
 * 模块作者：ZOUYONG
 * 开发时间：2019年4月10日 下午9:49:59
 * 模块路径：com.china.cnlongdb.server.connect.nettymission.LongdbNettyClient
 * 更新记录：
 */
public class LongdbNettyClient {

	// 传输服务IP
	private String serverIp;
	// 传输服务端口
	private int serverPort;
	// 需要发送到服务端的消息内容
	private String message;
	// 服务端返回的对象
	private Map<String, String> returnMap;
	// 用于同步返回的线程对象值
	private CountDownLatch doneSignal;
	
	// 构造函数
	public LongdbNettyClient(String serverIp, int serverPort, 
			String message, Map<String, String> returnMap, CountDownLatch doneSignal) {
		this.serverIp = serverIp;
		this.serverPort = serverPort;
		this.message = message;
		this.returnMap = returnMap;
		this.doneSignal = doneSignal;
		this.start();
	}

	/**
	 * 功能描述：连接服务端，并开启监听
	 * 模块作者：ZOUYONG
	 * 开发时间：2019年4月10日 下午9:46:49
	 * 更新记录：
	 * 返回数据：void
	 */
	private void start() {
		EventLoopGroup group = new NioEventLoopGroup();
		try {
			Bootstrap b = new Bootstrap();
			b.group(group) // 注册线程池
				.channel(NioSocketChannel.class) // 使用NioSocketChannel来作为连接用的channel类
				.remoteAddress(new InetSocketAddress(this.serverIp, this.serverPort)) // 绑定连接端口和host信息
				.handler(new ChannelInitializer<SocketChannel>() { // 绑定连接初始化器
					@Override
					protected void initChannel(SocketChannel ch) throws Exception {
						// System.out.println("正在连接服务端...");
						ch.pipeline().addLast(new StringEncoder(Charset.forName("utf-8")));
						ch.pipeline().addLast(new NettyClientHandler(message, returnMap, doneSignal));
						ch.pipeline().addLast(new ByteArrayEncoder());
					}
				});

			ChannelFuture cf = b.connect().sync();
			// System.out.println("异步连接服务器成功...");

			cf.channel().closeFuture().sync();
			// System.out.println("异步等待关闭连接channel..");
		}
		catch(Exception e) {
			throw new RuntimeException(e);
		}
		finally {
			try {
				if(null != group) {
					group.shutdownGracefully().sync(); // 释放线程池资源
				}
			} catch(Exception e) {
				throw new RuntimeException(e);
			}
		}
	}
	
	/**
	 * 功能描述：发送中国龙数据库的消息
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年4月11日 下午4:56:22
	 × 返回数据：String
	 */
	public static Map<String, String> sendNettyMessageByLongdb(String serverIp, int serverPort, Map<String, Object> dataMap) {
		// 中国龙数据库系统消息请求
		dataMap.put(LongdbDataSyncEnms.dataSyncType.name(), LongDbConstant.longdbName);
		return unifiedHandSendNettyMessage(serverIp, serverPort, dataMap);
	}
	
	/**
	 * 功能描述：向第三方系统发送网络消息
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年4月11日 下午5:01:15
	 × 返回数据：String
	 */
	public static Map<String, String> sendNettyMessageByThirdSystem(String serverIp, Integer serverPort, CnLongDataSyncRequest dataSync) {
		Map<String, Object> requestMap = new HashMap<String, Object>();
		// 第三方系统消息请求
		requestMap.put(LongdbDataSyncEnms.dataSyncType.name(), LongdbDataSyncEnms.thirdSystem.name());
		requestMap.put(LongdbDataSyncEnms.dataSyncContent.name(), dataSync);
		return unifiedHandSendNettyMessage(serverIp, serverPort, requestMap);
	}
	
	/**
	 * 功能描述：统一处理发送Netty通信请求
	 × 模块作者：ZOUYONG
	 × 开发时间：2019年4月30日 下午4:16:13
	 × 返回数据：String
	 */
	private static Map<String, String> unifiedHandSendNettyMessage(String serverIp, int serverPort, Map<String, Object> dataMap) {
		
		Map<String, String> returnMap = new HashMap<String, String>();
		String message = JSON.toJSONString(dataMap) + LongdbDataSyncEnms.cnlongNettySplitUnpooled.name();
		
		ExecutorService executor = Executors.newCachedThreadPool(); // 定义线程池
		CountDownLatch doneSignal = new CountDownLatch(1);
		executor.submit(new SendNettyRequest(serverIp, serverPort, message, returnMap, doneSignal));
		try {
			doneSignal.await(); // 等待所有线程完成操作
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		} finally {
			executor.shutdown(); // 关闭线程池
		}
		return returnMap;
	}
	
}
